/*-------------------------------------------------------------------------
 * logical.h
 *	   PostgreSQL 逻辑解码协调
 *
 * Copyright (c) 2012-2022, PostgreSQL Global Development Group
 *
 *-------------------------------------------------------------------------
 */
#ifndef LOGICAL_H
#define LOGICAL_H

#include "access/xlog.h"
#include "access/xlogreader.h"
#include "replication/output_plugin.h"
#include "replication/slot.h"

struct LogicalDecodingContext;

typedef void (*LogicalOutputPluginWriterWrite) (struct LogicalDecodingContext *lr,
												XLogRecPtr Ptr,
												TransactionId xid,
												bool last_write
);

typedef LogicalOutputPluginWriterWrite LogicalOutputPluginWriterPrepareWrite;

typedef void (*LogicalOutputPluginWriterUpdateProgress) (struct LogicalDecodingContext *lr,
														 XLogRecPtr Ptr,
														 TransactionId xid,
														 bool skipped_xact
);

typedef struct LogicalDecodingContext
{
	/* 这一切的内存上下文 */
	MemoryContext context;

	/* 关联的复制槽 */
	ReplicationSlot *slot;

	/* 解码的基础设施组件 */
	XLogReaderState *reader;
	struct ReorderBuffer *reorder;
	struct SnapBuild *snapshot_builder;

	/*
	 * 标记逻辑解码上下文为快速前进解码。这样的
	 * 上下文没有加载插件，因此以下大多数属性
	 * 是未使用的。
	 */
	bool		fast_forward;

	OutputPluginCallbacks callbacks;
	OutputPluginOptions options;

	/*
	 * 用户指定的选项
	 */
	List	   *output_plugin_options;

	/*
	 * 用户提供的回调，用于写入/流数据。
	 */
	LogicalOutputPluginWriterPrepareWrite prepare_write;
	LogicalOutputPluginWriterWrite write;
	LogicalOutputPluginWriterUpdateProgress update_progress;

	/*
	 * 输出缓冲区。
	 */
	StringInfo	out;

	/*
	 * 输出插件的私有数据指针。
	 */
	void	   *output_plugin_private;

	/*
	 * 数据写入器的私有数据指针。
	 */
	void	   *output_writer_private;

	/*
	 * 输出插件是否支持流式处理，并且是启用状态？
	 */
	bool		streaming;

	/*
	 * 输出插件是否支持两阶段解码，并且是启用状态？
	 */
	bool		twophase;

	/*
	 * 输出插件是否提供了两阶段选项？
	 *
	 * 此标志表明插件在START_STREAMING命令中
	 * 传递了两阶段选项。我们不能仅依赖于
	 * twophase标志，它只告诉我们插件是否提供了
	 * 所有必要的两阶段回调。
	 */
	bool		twophase_opt_given;

	/*
	 * 输出写入的状态。
	 */
	bool		accept_writes;
	bool		prepared_write;
	XLogRecPtr	write_location;
	TransactionId write_xid;
	/* 我们正在处理事务的结束LSN吗？ */
	bool		end_xact;
#ifdef FDD
	FDB_WalSndKeepaliveCallback fdb_keepalive_cb;
	bool failover_logical;
#endif

	/*
	 * 如果用于创建逻辑复制槽的逻辑解码上下文则为真。
	 */
	bool		in_create;
} LogicalDecodingContext;


extern void CheckLogicalDecodingRequirements(void);

extern LogicalDecodingContext *CreateInitDecodingContext(const char *plugin,
														 List *output_plugin_options,
														 bool need_full_snapshot,
														 XLogRecPtr restart_lsn,
														 XLogReaderRoutine *xl_routine,
														 LogicalOutputPluginWriterPrepareWrite prepare_write,
														 LogicalOutputPluginWriterWrite do_write,
														 LogicalOutputPluginWriterUpdateProgress update_progress);
extern LogicalDecodingContext *CreateDecodingContext(XLogRecPtr start_lsn,
													 List *output_plugin_options,
													 bool fast_forward,
													 XLogReaderRoutine *xl_routine,
													 LogicalOutputPluginWriterPrepareWrite prepare_write,
													 LogicalOutputPluginWriterWrite do_write,
													 LogicalOutputPluginWriterUpdateProgress update_progress);
extern void DecodingContextFindStartpoint(LogicalDecodingContext *ctx);
extern bool DecodingContextReady(LogicalDecodingContext *ctx);
extern void FreeDecodingContext(LogicalDecodingContext *ctx);

extern void LogicalIncreaseXminForSlot(XLogRecPtr lsn, TransactionId xmin);
extern void LogicalIncreaseRestartDecodingForSlot(XLogRecPtr current_lsn,
												  XLogRecPtr restart_lsn);
extern void LogicalConfirmReceivedLocation(XLogRecPtr lsn);

extern bool filter_prepare_cb_wrapper(LogicalDecodingContext *ctx,
									  TransactionId xid, const char *gid);
extern bool filter_by_origin_cb_wrapper(LogicalDecodingContext *ctx, RepOriginId origin_id);
extern void ResetLogicalStreamingState(void);
extern void UpdateDecodingStats(LogicalDecodingContext *ctx);

#endif
